#include "ClientFunc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "StdTcp.h"
#include "Clientdatacenter.h"


int LoginFace()
{
    printf("===================聊天室登录========================\n");
    printf("1、注册\n");
    printf("2、登录\n");
    printf("====================================================\n");
    printf("请选择你要的功能:");
    int choice = 0;
    scanf("%d",&choice);
    return choice * (-1);
}

MSG SignUp(char *MyName)
{
    MSG m;
    m.flag = SIGNUP;  //注册用户名
    printf("===================注册新用户====================\n");
    printf("请输入你的用户名:");
    scanf("%s",m.FromName);
    printf("请输入你的密码:");
    scanf("%s",m.Content);
    printf("================================================\n");
    strcpy(MyName,m.FromName);
    return m;
}

bool IsSignUpSuccess(MSG * m)
{
    if(strcmp(m->Content,"注册成功") == 0)
    {
        printf("注册成功！欢迎来到聊天室\n");
        return true;
    }
    else
    {
        printf("注册错误:%s\n",m->Content);
        return false;
    }
}

MSG Login(char * MyName)
{
    MSG m;
    m.flag = LOGIN;  //登录用户名
    printf("===================登录=========================\n");
    printf("请输入你的用户名:");
    scanf("%s",m.FromName);
    printf("请输入你的密码:");
    scanf("%s",m.Content);
    printf("================================================\n");
    strcpy(MyName,m.FromName);
    return m;
}

bool IsLoginSuccess(MSG * m)
{
    if(strcmp(m->Content,"登录成功") == 0)
    {
        printf("登录成功！欢迎来到聊天室\n");
        return true;
    }
    else
    {
        printf("登录错误:%s\n",m->Content);
        return false;
    }
}

int Interface()
{
    printf("===================欢迎来到聊天室====================\n");
    printf("1、私聊\n");
    printf("2、广播\n");
    printf("3、查看在线用户\n");
    printf("4、文件发送\n");
    printf("5、我的网盘\n");
    printf("6、好友管理\n");
    printf("7、群管理\n");
    printf("====================================================\n");
    printf("请选择你要的功能:");
    int choice = 0;
    scanf("%d",&choice);
    return choice;
}

MSG ChatBroadCast()
{
    MSG m;
    m.flag = BROADCAST;
    printf("请输入你要发送的信息:");
    scanf("%s",m.Content);
    return m;
}

MSG GetServerOnlineList()
{
    MSG m;
    m.flag = ONLINELIST;
    return m;
}

MSG ChatToClient()
{
    MSG m;
    m.flag = CHAT;
    printf("请输入你要发送的用户名称:");
    scanf("%s",m.ToName);
    printf("请输入你要发送的信息:");
    scanf("%s",m.Content);
    return m;
}

void ShowOnlineList(MSG *m)
{
    char str[ContentSize] = {0};
    strcpy(str,m->Content);
    char *dest = strtok(str,",");
    int count = 1;
    while(dest != NULL)
    {
        printf("%d:%s\n",count++,dest);
        dest = strtok(NULL,",");
    }
}

MSG SendFile()
{
    MSG m;
    m.flag = SENDFILE;
    printf("请输入你要发送的文件路径:");
    scanf("%s",m.Content);
    printf("请输入你要发送的用户:");
    scanf("%s",m.ToName);
    return m;
}

char * GetFileNameFromPath(const char * filePath)
{
    char str[ContentSize] = {0};
    strcpy(str,filePath);

    char *dest = strtok(str,"/");
    char *fileName = NULL;
    while(dest != NULL)
    {
        fileName = dest;
        dest = strtok(NULL,"/");
    }
    char *result = strdup(fileName);
    return result;
}

// 将此次接受到的消息内容追加写入本地文件中
void WriteToLocal(MSG * m)
{
    int size = 0;
    memcpy(&size,m->Content,sizeof(int));
    char fileName[NameSize] = {0};
    strcpy(fileName,m->Content + 4);

    char filePath[ContentSize] = {0};
    sprintf(filePath,"./%s",fileName);
    FILE *f = fopen(filePath,"a");
    fwrite(m->Content+24,size,1,f);
    fclose(f);
}

// 我的网盘界面
int CloudInterface()
{
    printf("=====================我的网盘=========================\n");
    printf("1、查看网盘文件\n");
    printf("2、上传文件\n");
    printf("3、下载文件\n");
    printf("4、退回到主界面\n");
    printf("======================================================\n");
    printf("请输入你的选择:");
    int choice = 0;
    scanf("%d",&choice);
    return FILELIST + choice - 1;
}

MSG UpLoadFile()
{
    MSG m;
    m.flag = UPLOAD;// 服务器识别你的需求
    printf("请输入要上传的文件路径:");
    scanf("%s",m.Content);
    return m;
}

// 下载文件
MSG DownLoadFile()
{
    MSG m;
    m.flag = DOWNLOAD;
    printf("请输入你要下载的文件名:");
    scanf("%s",m.Content);
    return m;
}

// 通用的字符串切割函数
/*
    这一行定义了函数 Splite，它接受三个参数：
        str：指向要分割的常量字符数组（字符串）的指针。
        delim：指向用于分割输入字符串的分隔符的常量字符数组（字符串）的指针。
        size：一个整数指针，用于存储结果数组的大小。
*/
char ** Splite(const char * str, const char *delim, int * size)// 字符串数组所以用char **
{
    char *splitStr = strdup(str);// 使用 strdup 函数创建了输入字符串 str 的副本。这个副本是必要的，因为 strtok 会修改原始字符串，我们不希望修改输入字符串。

    char **result = (char **)malloc(sizeof(char *) * 50);// result 将保存分割后的各个子字符串的指针。
    if(result == NULL)
    {
        printf("Splite malloc error!\n");
        return NULL;
    }

    int count = 0;// 用于跟踪找到的子字符串数量
    char *dest = strtok(splitStr, delim);// 指向使用分隔符 delim 将 splitStr 分割后得到的第一个标记（子字符串）
    while(dest != NULL)
    {
        result[count++] = strdup(dest);//
        dest = strtok(NULL, delim);// 它通过使用 NULL 作为第一个参数调用 strtok 来更新 dest，指向下一个标记
    }

    free(splitStr);// 释放了为 splitStr 分配的内存
    *size = count;// 使用找到的子字符串数量（count）更新了 size 参数
    return result;// 返回指向包含子字符串指针的数组 result 的指针。
}

// 释放字符串
void FreeStrList(char ** strList, int size)
{
    for(int i = 0; i < size; i++)
    {
        free(strList[i]);
    }
    free(strList);// 最后释放自己
}

// 显示文件列表
void showFileList(MSG *m)
{
    if (strcmp(m->Content,"FILELISTERROR") == 0)
    {
        printf("获取网盘文件失败!\n");
        return;
    }
    
    int fileCount = 0;
    char ** file = Splite(m->Content, ",", &fileCount);

    for (int i = 0; i < fileCount; i++)
    {
        int count = 0;
        char ** fileInfo = Splite(file[i], ";", &count);
        if (count != 2)
        {
            FreeStrList(fileInfo, count);
            continue;
        }
        // 经过两层拆分，我们就获得文件名和文件大小
        printf("%d : 文件名: |%s|, 文件大小 : |%s|\n", i+1, fileInfo[0], fileInfo[1]);
        FreeStrList(fileInfo, count);
    }
    FreeStrList(file, fileCount);

}

// 文件结构体
struct PacketFile
{
    FILE *f;//文件指针
    long FileSize;//文件大小
    long currentPosition;//当前位置
};

//  初始化文件结构体 返回文件结构体指针
PackFile * PacketFileInit(const char * FilePath)
{
    PackFile *pf = (PackFile *)malloc(sizeof(PackFile));
    if(pf == NULL)
    {
        printf("PacketFileInit malloc error!\n");
        return NULL;
    }

    pf->f = fopen(FilePath,"r");
    if(pf->f == NULL)
    {
        printf("打开|%s|文件失败!\n",FilePath);
        free(pf);
        return NULL;
    }
    //计算文件大小
    fseek(pf->f,0,SEEK_END);
    pf->FileSize = ftell(pf->f);
    fseek(pf->f,0,SEEK_SET);

    pf->currentPosition = 0;
    printf("文件大小：%ld,文件位置:%ld\n",pf->FileSize,pf->currentPosition);
    return pf;
}

// 从文件f读取size大小的数据，并更新当前位置
void ReadFromFile(PackFile * f, void * p, int * size)
{
    if(*size + f->currentPosition > f->FileSize)
    {
        *size = f->FileSize - f->currentPosition;
    }
    fread(p,*size,1,f->f);
    f->currentPosition += *size;
}

// 判断文件是否已经读完
bool IsFileEnd(PackFile * f)
{
    return f->currentPosition == f->FileSize;
}

// 释放文件结构体
void ClearPacketFile(PackFile * f)
{
    fclose(f->f);
    free(f);
}


// 好友管理界面
int FriendManageInterface()
{
    printf("=====================好友管理=========================\n");
    printf("1、添加好友\n");
    printf("2、我的好友列表\n");
    printf("3、删除好友\n");
    printf("4、好友聊天\n");
    printf("5、我的好友申请\n");
    printf("6、回复好友申请\n");
    printf("7、退回到主界面\n");
    printf("======================================================\n");
    printf("请输入你的选择:");
    int choice = 0;
    scanf("%d",&choice);
    return ADDFRIEND + choice - 1;
}

// 添加好友
MSG AddNewFriend()
{
    MSG m;
    memset(&m, 0, sizeof(m));
    m.flag = ADDFRIEND;
    printf("请输入你要添加的好友名称:");
    scanf("%s",m.ToName);
    return m;
}

// 我的好友列表
bool ShowMyFriendList(const char *list)
{
    if(strlen(list) == 0)
    {
        printf("好友列表为空......\n");
        return false;
    }
    int size = 0;
    // 将好友列表字符串按分号切割，并返回切割后的字符串数组和数组大小
    char **friends = Splite(list, ";", &size);
    printf("friends list:\n");
    // 遍历切割后的好友数组，并打印每个好友
    for(int i = 0; i < size; i++)
    {
        printf("%d:%s\n", i + 1, friends[i]);
    }
    FreeStrList(friends, size);// 释放内存
    return true;
}

// 删除好友
MSG DeleteFriend()
{
    MSG m;
    memset(&m, 0, sizeof(MSG));
    m.flag = DELETEFRIEND;
    char name[NameSize] = { 0 };// 存储
    printf("请输入你要删除的好友名称:\n");
    scanf("%s",name);
    // 将用户输入的好友名称拷贝到消息的内容字段 m.Content 中
    strcpy(m.Content, name);
    return m;
}


//好友聊天循环
void FriendChatLoop(TcpC *c,const char* myname)
{
    printf("=====好友聊天界面=====\n");
    MSG m;// 消息
    while(1)
    {
        printf("---------------------------\n");
        printf("---------------------------");
        printf("\n");
        // 提示用户，输入ESC可以退出聊天
        printf("在消息框中输入ESC可以退出聊天\n");

        memset(&m, 0, sizeof(MSG));
        strcpy(m.FromName, myname);
        m.flag = FRIENDCHAT;
        // 提示并获取好友的名称
        printf("好友名称:");
        scanf("%s", m.ToName);
        
        // 提示并获取消息内容
        printf("消息内容:");
        scanf("%s", m.Content);

        // 如果消息内容的第一个字符是ESC (ASCII 27)，则退出循环
        if (m.Content[0] == 27)
        {
            break;
        }
        
        // 将消息存储到本地数据库
        ClientInterMessage(&m);
  
        TcpClientSend(c, &m, sizeof(MSG));
        // 休眠1秒，避免频繁发送消息
        sleep(1);

    }

}

//好友聊天消息展示
void ShowFriendMessages(MSG messages[],const char *myname,int size)
{
    // 清屏，清除终端内容
    system("clear");
    printf("---------------------------\n");
    printf("---------------------------");
    printf("\n");

    // 遍历消息数组，并打印每个消息
    for (int i = 0; i < size; i++)
    {
        // 如果消息的发送者是当前用户
        if (strcmp(messages[i].FromName, myname) == 0)
        {
            // 右对齐显示消息发送者名称和消息内容
            printf("%70s %s\n", messages[i].FromName, messages[i].Content);
            // 显示消息内容的后80个字符，假设消息内容超过80个字符
            printf("%70s\n", messages[i].Content+80);
        }
        else
        {
            // 如果消息的发送者不是当前用户
            // 左对齐显示消息发送者名称和消息内容
            printf("%s %s\n", messages[i].FromName, messages[i].Content);
            // 显示消息内容的后80个字符，假设消息内容超过80个字符
            printf("%s\n", messages[i].Content+80);
        }
    }
    printf("---------------------------\n");
    printf("---------------------------");
    printf("\n");
}

// 好友添加响应
int FriendAddResponse(const char *name)
{
    printf("用户|%s|发送了好友请求,您是否同意添加？\n", name);
    int choice = 0;
    printf("1、同意\n");
    printf("2、拒绝\n");
    
    scanf("%d",&choice);
    return choice;
}

// 展示好友申请列表
int ShowFriendApplyList(const char *list)
{
    if(strlen(list) == 0)
    {
        printf("好友申请列表为空......\n");
        return 0;// 返回0表示没有好友申请
    }
    char strlist[ContentSize] = {0};
    strcpy(strlist,list);// 传入的好友申请列表字符串拷贝到 strlist
    return 0;
}

// 客户端回应好友申请
MSG ResponseFriendApplication()
{
    MSG m;
    memset(&m, 0, sizeof(m));
    m.flag = CALLFRIENDREQUEST;
    printf("请输入你要回复的好友申请的名称:");
    scanf("%s",m.ToName);
    return m;
}


// 群管理界面
int GroupManageInterface()
{
    printf("=====================群管理=========================\n");
    printf("1、创建群\n");
    printf("2、添加群成员\n");
    printf("3、邀请入群通知\n");
    printf("4、处理入群邀请\n");
    printf("5、群聊\n");
    printf("6、我的群列表\n");
    printf("7、删除群\n");
    printf("8、退回到主界面\n");
    printf("======================================================\n");
    printf("请输入你的选择:");
    int choice = 0;
    scanf("%d",&choice);
    return CREATEGROUP + choice - 1;
}

//创建群
MSG GroupCreate()
{
    MSG m;
    memset(&m,0,sizeof(MSG));
    m.flag = CREATEGROUP;
    printf("请输入需要创建的群的名称:");
    scanf("%s",m.Content);
    return m;
}

//邀请入群
MSG InviteWhoGroup()
{
    MSG m;
    memset(&m,0,sizeof(MSG));
    m.flag = VISITWHOJOINGROUP;
    printf("请输入你想邀请的用户名称:");
    scanf("%s",m.ToName);
    printf("请输入你想邀请的群名:");
    scanf("%s",m.Content);
    return m;
}

//展示群邀请信息
void ShowGroupInvite(MSG *m)
{
    int invitioncount = 0;
    // 用分号 ";" 分割字符串 m->Content，分割后的子字符串存入 intvition 数组中，分割的数量存入 invitioncount
    char **intvition = Splite(m->Content,";",&invitioncount);//文件名+大小
    for (int i = 0; i < invitioncount; i++)
    {
        int count = 0;
        // 分割每个邀请信息，返回分割后的字符串数组和分割数量
        char **invitionInfo = Splite(intvition[i],",",&count);
        if (count != 2)
        {
            FreeStrList(invitionInfo,count);
            continue;//处理下一个邀请信息
        }
        printf("%d : 管理员:|%s| 邀请您加入:|%s|\n",i+1,invitionInfo[0],invitionInfo[1]);
        FreeStrList(invitionInfo,count);
    }
    FreeStrList(intvition,invitioncount);// 释放
}

//处理群邀请通知
MSG HandleInviteFunc()
{
    MSG m;
    memset(&m,0,sizeof(MSG));
    m.flag = PROCESSGROUPINVITATION;
    printf("请按照提示输入信息,若想退出在输入框中输入ESC即可\n");
    printf("请输入你同意加入的群组:");
    scanf("%s",m.Content);
    return m;
}

//群聊
void GroupChatLoop(TcpC*c,const char *myname, const char *groupname)
{
    printf("欢迎进入群聊天界面\n");
    MSG m;
    while (1)
    {
        for (int i = 0; i < 80; i++)
            printf("=");
        printf("\n");
        printf("按照提示输入消息,在消息框中输入ESC退出聊天\n");
        memset(&m,0,sizeof(MSG));
        strcpy(m.FromName,myname);
        m.flag = GROUPMESSAGERECORD;
        strcpy(m.ToName,groupname);
        printf("消息内容:");
        scanf("%s",m.Content);
        if (m.Content[0] == 27)// ESC退出
        {
            break;
        }
        ClientInterMessage(&m);
        TcpClientSend(c,&m,sizeof(MSG));
        sleep(1);
    }
}

//展示群组消息
void ShowGroupMessages(MSG messages[],const char *myname,int size)
{
    // 清屏，清除终端内容
    system("clear");
    for (int i = 0; i < 80; i++)
    {
        printf("=");
    }
    printf("\n");
    printf("%s聊天室||\n",messages[0].ToName);
    printf("===========");
    for (int i = 0; i < size; i++)
    {
        if (strcmp(messages[i].FromName,myname) == 0)
        {
            // 右对齐显示消息发送者名称和消息内容
            printf("%70s %s\n", messages[i].FromName, messages[i].Content);
            printf("%70s\n", messages[i].Content+80);
        }
        else
        {
            // 如果消息的发送者不是当前用户
            // 左对齐显示消息发送者名称和消息内容
            printf("%s %s\n", messages[i].FromName, messages[i].Content);
            printf("%s\n", messages[i].Content+80);
        }
        
    }
    for (int i = 0; i < 80; i++)
    {
        printf("=");
    }
    printf("\n");
}

//群列表
void ShowGroupList(MSG *m)
{
    if (strlen(m->Content) == 0)
    {
        printf("grouplist is null\n");
        return ;
    }
    int count = 0;
    char **list = Splite(m->Content,",",&count);
    for (int i = 0; i < count; i++)
    {
        printf("%d %s\n",i + 1,list[i]);
    }
    return ;
}

//删除群
MSG DeleteGroup()
{
    MSG m;
    memset(&m, 0, sizeof(MSG));
    m.flag = DELETEGROUP;
    char group[NameSize] = { 0 };// 存储
    printf("请输入你要删除的群名称:\n");
    scanf("%s",group);
    // 将用户输入的群名称拷贝到消息的内容字段 m.Content 中
    strcpy(m.Content, group);
    return m;
}

